package pe.gob.foncodes.ssa.web.controller;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.HashMap;
import javax.faces.bean.ManagedBean;
import javax.faces.event.ActionEvent;
import org.apache.log4j.Logger;
import org.primefaces.context.RequestContext;
import org.primefaces.event.SelectEvent;
import org.primefaces.model.DefaultTreeNode;
import org.primefaces.model.TreeNode;
import pe.gob.foncodes.ssa.bs.administracion.controller.GenericMaintenanceController;
import pe.gob.foncodes.ssa.bs.common.util.Constante;
import pe.gob.foncodes.ssa.bs.common.util.ServiceException;
import pe.gob.foncodes.ssa.bs.seguridad.domain.ConfiguracionModulo;
import pe.gob.foncodes.ssa.bs.seguridad.domain.ControlAcceso;
import pe.gob.foncodes.ssa.bs.seguridad.domain.General;
import pe.gob.foncodes.ssa.bs.seguridad.domain.Modulo;
import pe.gob.foncodes.ssa.bs.seguridad.domain.Opcion;

/**
 *
 * @author aespinoza
 */
@ManagedBean(name = "moduloController")
public class ModuloController extends GenericMaintenanceController{

    protected static Logger log = Logger.getLogger(ModuloController.class);
    private boolean esNuevo;
    private String txtBusquedaModulo;
    private String mensaje;
    private TreeNode moduloTree;
    private TreeNode selectedModuloNode; 
    private boolean BMuestraObs;
    private boolean BActivo;
    
    private List<General> lstTipoModulo = new ArrayList<General>();
    private Map<String, String> mapaTipoModulo = new HashMap<String, String>();
    
    private List<Modulo> lstModulo = new ArrayList<Modulo>();
    private Modulo selectedModulo;
    
    private List<Modulo> lstModuloPadre = new ArrayList<Modulo>();
    private Modulo selectedModuloPadre;
    
    private ConfiguracionModulo selectedConfiguracion;
    private int numTiempoSesion;
    private int numTiempoBloqueoSinuso;
    
    @Override
    public void init() {
        mensaje = "";
        setBean(new Modulo());
        selectedModulo = null;
        selectedModuloNode = null;
        selectedModuloPadre = null;
        esNuevo = false;
        BMuestraObs = false;
        this.txtBusquedaModulo="";
        loadInicialTree();
        try {
            lstTipoModulo = getService().findByNamedQuery("General.findByTxtDominio", new Object[]{Constante.DOMINIO_TIPO_MODULO});
            mapaTipoModulo = new HashMap<String, String>();
            for (General general : lstTipoModulo) {
                mapaTipoModulo.put(general.getTxtValor(), general.getTxtParametro());
            }
        } catch (Exception e) {
        }
        selectedConfiguracion = null;
    }

    @Override
    public void search(ActionEvent event) throws Exception{
        selectedModulo = null;
        selectedModuloNode = null;
        listar();
    }
    
    public void listar() throws ServiceException{
        if(this.txtBusquedaModulo == null){
            this.txtBusquedaModulo = "";
        }
        if(txtBusquedaModulo.trim().equals("")){
            lstModulo = getService().findByNamedQuery("Modulo.findOnlyNidModuloPadre");
        }else{
            lstModulo = getService().findByNamedQuery("Modulo.findByTxtModulo", new Object[]{"%" + txtBusquedaModulo.trim().toUpperCase() + "%"});
        }
        setBeanList(lstModulo);
        if(selectedModulo != null){
            moduloTree = new DefaultTreeNode("root", null);
            loadPadreTree(selectedModulo);
        }
    }
     
    public void onRowSelect(SelectEvent event) {
        moduloTree = new DefaultTreeNode("root", null);
        selectedModulo = (Modulo) event.getObject();
        try {
            loadPadreTree(selectedModulo);
        } catch (ServiceException ex) {
            log.error("ERROR EN onRowSelect: "+ex);
        }
    }
    
    public void loadInicialTree(){
        selectedModulo = null;
        selectedModuloNode = null;
        moduloTree = new DefaultTreeNode("root", null);
        try {
            List<Modulo> lstModuloInicial = getService().findByNamedQuery("Modulo.findOnlyNidModuloPadre");
            lstModulo = new ArrayList<Modulo>();
            for (Modulo modulo : lstModuloInicial) {
                lstModulo.add(modulo);
                TreeNode padre = new DefaultTreeNode(modulo, moduloTree);
            }
            setBeanList(lstModulo);
        } catch (ServiceException ex) {
            log.error("ERROR EN loadInicialTree: "+ex);
        }
    }
    
    public void loadPadreTree(Modulo selectedModulo) throws ServiceException {
        moduloTree = new DefaultTreeNode("root", null);
        TreeNode padre = new DefaultTreeNode(selectedModulo, moduloTree);
        padre.setExpanded(true);
        selectedModuloNode = padre;
        
        List<Modulo> lstModuloHijos = new ArrayList<Modulo>();
        try {
            lstModuloHijos = getService().findByNamedQuery("Modulo.findByNidModuloPadre", new Object[]{selectedModulo.getId()});
            for (Modulo hijoMo : lstModuloHijos) {
                TreeNode hijo = new DefaultTreeNode(hijoMo, padre);
                hijo.setExpanded(true);
                loadHijoTree(hijo, hijoMo);
            }
        } catch (ServiceException ex) {
            log.error("ERROR EN loadPadreTree: "+ex);
        }
    }
    
    public void loadHijoTree(TreeNode hijo, Modulo moHijo) throws ServiceException {
        List<Modulo> lstModuloHijos = getService().findByNamedQuery("Modulo.findByNidModuloPadre", new Object[]{moHijo.getId()});
        for (Modulo modulo : lstModuloHijos) {
            TreeNode nieto = new DefaultTreeNode(modulo, hijo);
            nieto.setExpanded(true);
            loadHijoTree(nieto, modulo);
        }
    }
    
    public void muestraObservacion() {  
        BMuestraObs = (BActivo)?false:true;
    }
    
    public void nuevo() {
        RequestContext context = RequestContext.getCurrentInstance();
        BActivo = true;
        esNuevo = true;
        BMuestraObs = false;
        Modulo modulo = new Modulo();
        if(selectedModuloNode != null){
            modulo.setNidModuloPadre((Modulo) selectedModuloNode.getData());
        }
        setBean(modulo);
        context.execute("wDetalleModulo.show()");
    }
    
    @Override
    public void load(ActionEvent event) throws Exception {
        RequestContext context = RequestContext.getCurrentInstance();
        if(selectedModuloNode == null){
            setMessageError(new Exception("Debe seleccionar un modulo del árbol"));
            esNuevo = false;
        }else {
            esNuevo = false;
            Modulo mod = (Modulo) selectedModuloNode.getData();
            mod = (Modulo) getService().findById(Modulo.class, mod.getId());
            setBean(mod);
            BActivo = false;
            if(mod.getFlgActivo() != null){
                if(mod.getFlgActivo().equals(Constante.ESTADO_ACTIVO)){
                    BActivo = true;
                }else{
                    BActivo = false;
                }
            }
            if(BActivo){
                BMuestraObs = false;
            }else{
                BMuestraObs = true;
            }
            context.execute("wDetalleModulo.show()");
        }
    }
    
    public void searchModuloPadre(){
        Modulo modulo = (Modulo)getBean();
        Long NidModulo = modulo.getId();
        lstModuloPadre = new ArrayList<Modulo>();
        Modulo moduloTmp =null;
        for (TreeNode nodePadre : moduloTree.getChildren()) {
            moduloTmp = (Modulo) nodePadre.getData();
            if(!moduloTmp.getId().equals(NidModulo)){
                lstModuloPadre.add(moduloTmp);
            }
            if(!nodePadre.getChildren().isEmpty()){
                if(!moduloTmp.getId().equals(NidModulo)){
                    lstModuloPadre = listaHijos(lstModuloPadre, nodePadre, NidModulo);
                }
                
            }
        }
        selectedModuloPadre = null;
    }
    
    public List<Modulo> listaHijos(List<Modulo> lstModuloPadreTmp, TreeNode nodo, Long NidModuloPadre){
        Modulo moduloTmp =null;
        for (TreeNode nodeTmp : nodo.getChildren()) {
            moduloTmp = (Modulo) nodeTmp.getData();
            if(!moduloTmp.getId().equals(NidModuloPadre)){
                lstModuloPadreTmp.add(moduloTmp);
            }
            if(!nodeTmp.getChildren().isEmpty()){
                if(!moduloTmp.getId().equals(NidModuloPadre)){
                    lstModuloPadreTmp = listaHijos(lstModuloPadreTmp, nodeTmp, NidModuloPadre);
                }
            }
        }
        return lstModuloPadreTmp;
    }
    
    public void actualizaModuloSeleccion(Modulo moduloAct) {
        this.selectedModuloPadre = moduloAct;
        Modulo modulo = (Modulo)getBean();
        modulo.setNidModuloPadre(selectedModuloPadre);
        setBean(modulo);
    }
    
    public void abrirOpciones() {
        RequestContext context = RequestContext.getCurrentInstance();
        if(selectedModuloNode == null){
            setMessageError(new Exception("Debe seleccionar un modulo del árbol"));
        }else {
            if(((Modulo)selectedModuloNode.getData()).getFlgActivo().equals(Constante.ESTADO_INACTIVO)){
                setMessageError(new Exception("El modulo se encuentra desactivado"));
            }else{
                limpiarOpciones();
                context.execute("wGestionarOpciones.show()");
            }
        }
    }
    
    public void limpiarOpciones(){
        OpcionController opcionController = (OpcionController) getSpringBean("opcionController");
        opcionController.setSelectedModuloOpcion((Modulo)selectedModuloNode.getData());
        opcionController.setTxtBusquedaOpcion("");
        opcionController.setLstOpcion(new ArrayList<Opcion>());
        opcionController.loadInicialTree();
    }
    
    public void abrirParametros() {
        RequestContext context = RequestContext.getCurrentInstance();
        if(selectedModuloNode == null){
            setMessageError(new Exception("Debe seleccionar un modulo del árbol"));
        }else {
            if(((Modulo)selectedModuloNode.getData()).getFlgActivo().equals(Constante.ESTADO_INACTIVO)){
                setMessageError(new Exception("El modulo se encuentra desactivado"));
            }else{
                obtenerConfiguracionPorModulo();
                context.execute("wGestionarParametro.show()");
            }
        }
    }
    
    public void obtenerConfiguracionPorModulo() {
        Modulo modulo = (Modulo)selectedModuloNode.getData();
        numTiempoSesion = 0;
        numTiempoBloqueoSinuso = 0;
        try {
            List<ConfiguracionModulo> lista = getService().findByNamedQuery("ConfiguracionModulo.findByNidModulo", new Object[]{modulo.getId()});
            if(lista.isEmpty()){
                esNuevo=true;
                selectedConfiguracion = new ConfiguracionModulo();
                selectedConfiguracion.setNumTiempoBloqueoSinuso(0);
                selectedConfiguracion.setNumTiempoSesion(0);
                selectedConfiguracion.setNidModulo(modulo);
            }else{
                esNuevo=false;
                selectedConfiguracion = lista.get(0);
                if(selectedConfiguracion.getNumTiempoSesion() != null){
                    numTiempoSesion = selectedConfiguracion.getNumTiempoSesion();
                }
                if(selectedConfiguracion.getNumTiempoBloqueoSinuso() != null){
                    numTiempoBloqueoSinuso = selectedConfiguracion.getNumTiempoBloqueoSinuso();
                }
            }
            setBean(modulo);
        } catch (Exception e) {
            log.error("ERROR EN obtenerConfiguracionPorModulo: "+e);
        }
    }
    
    public void guardarConfiguracion(ActionEvent event){
        RequestContext context = RequestContext.getCurrentInstance();
        Modulo modulo = (Modulo)getBean();
        ControlAcceso control = ((ControlAcceso) getSpringBean(Constante.SESSION_ACCESO));
        try {
            selectedConfiguracion.setNumTiempoSesion(numTiempoSesion);
            selectedConfiguracion.setNumTiempoBloqueoSinuso(numTiempoBloqueoSinuso);
            selectedConfiguracion.setNIdCtrlAccesoWeb(control.getId());
            setBean(selectedConfiguracion);
            if(esNuevo){
                super.beforeSave(event);
                super.doSave(event);
            }else{
                super.beforeUpdate(event);
                super.doUpdate(event);
            }
            setMessageSuccess("Se actualizó la configuración del módulo " + "'" + modulo.getTxtModulo() + "'" + " satisfactoriamente.");
            log.info("End of Transaction: 'Update'");
            context.execute("wGestionarParametro.hide()");
            setBean(modulo);
        } catch (Exception e) {
            log.error("ERROR EN guardarConfiguracion: "+e);
        }
    }
    
    @Override
    public void clean(ActionEvent event) throws Exception {
        setBean(new Modulo());
        selectedModuloNode = null;
    }
    
    @Override
    public boolean validate() throws Exception {
        boolean success = true;
        Modulo modulo = (Modulo)getBean();
        if (modulo.getTxtModulo() == null ){
            modulo.setTxtModulo("");
        }
        if(modulo.getTxtModulo().trim().equals("")) {
            setMessageError(new Exception("Se debe ingresar el nombre."));
            success = false;
            return success;
        }

        /*if (!modulo.getTxtModulo().equals("")) {
            List listaModulo = getService().findByObjectDif("Modulo", "txtModulo", modulo.getTxtModulo().trim(), modulo.getId());
            if (listaModulo != null && listaModulo.size() != 0) {
                setMessageError(new Exception("Ya existe un modulo registrado con el mismo nombre."));
                success = false;
                return success;
            }
        }*/
        if (modulo.getTipModulo() == null ){
            modulo.setTipModulo("-1");
        }
        
        if(modulo.getTipModulo().equals(Constante.NO_OPTION_SELECTED)) {
            setMessageError(new Exception("Debe seleccionar el tipo de modulo."));
            success = false;
            return success;
        }
        
        if(modulo.getFlgActivo().equals(Constante.ESTADO_INACTIVO)) {
            if (modulo.getTxtObservacion() == null ){
                modulo.setTxtObservacion("");
            }
            if(modulo.getTxtObservacion().equals("")){
                setMessageError(new Exception("Se debe ingresar la observación."));
                success = false;
                return success;
            }
        }
        if(modulo.getFlgActivo().equals(Constante.ESTADO_ACTIVO) && !esNuevo) {
            modulo.setTxtObservacion(null);
        }
        return success;
    }
    
    public void saveModulo(ActionEvent event) throws Exception {
        RequestContext context = RequestContext.getCurrentInstance();
        Modulo modulo = (Modulo)getBean();
        ControlAcceso control = ((ControlAcceso) getSpringBean(Constante.SESSION_ACCESO));
        modulo.setFlgActivo((BActivo)?Constante.ESTADO_ACTIVO:Constante.ESTADO_INACTIVO);
        modulo.setNIdCtrlAccesoWeb(control.getId());
        setBean(modulo);
        try {
            //Nuevo
            if(esNuevo){
                if (validate()) {
                    super.beforeSave(event);
                    super.doSaveSinProp(event);
                    afterSave(event);
                    context.execute("wDetalleModulo.hide()");
                }
            //Modificar
            }else{
                if (validate()) {
                    super.beforeUpdate(event);
                    super.doUpdate(event);
                    afterUpdate(event);
                    context.execute("wDetalleModulo.hide()");
                }
            }
        } catch (Exception e) {
            log.error("ERROR EN saveModulo: "+e);
        }
    }
    
    @Override
    public void afterSave(ActionEvent event) throws Exception {
        esNuevo = false;
        setMessageSuccess("Se creo el módulo " + "'" + ((Modulo) getBean()).getTxtModulo() + "'" + " satisfactoriamente.");
        log.info("End of Transaction: 'Save'");
    }
    
    @Override
    public void afterUpdate(ActionEvent event) throws Exception {
        setMessageSuccess("Se actualizó el módulo " + "'" + ((Modulo) getBean()).getTxtModulo() + "'" + " satisfactoriamente.");
        log.info("End of Transaction: 'Update'");
    }
    
    public boolean isEsNuevo() {
        return esNuevo;
    }

    public void setEsNuevo(boolean esNuevo) {
        this.esNuevo = esNuevo;
    }

    public String getMensaje() {
        return mensaje;
    }

    public void setMensaje(String mensaje) {
        this.mensaje = mensaje;
    }

    public String getTxtBusquedaModulo() {
        return txtBusquedaModulo;
    }

    public void setTxtBusquedaModulo(String txtBusquedaModulo) {
        this.txtBusquedaModulo = txtBusquedaModulo;
    }

    public TreeNode getModuloTree() {
        return moduloTree;
    }

    public void setModuloTree(TreeNode moduloTree) {
        this.moduloTree = moduloTree;
    }

    public List<Modulo> getLstModulo() {
        return lstModulo;
    }

    public void setLstModulo(List<Modulo> lstModulo) {
        this.lstModulo = lstModulo;
    }

    public Modulo getSelectedModulo() {
        return selectedModulo;
    }

    public void setSelectedModulo(Modulo selectedModulo) {
        this.selectedModulo = selectedModulo;
    }

    public TreeNode getSelectedModuloNode() {
        return selectedModuloNode;
    }

    public void setSelectedModuloNode(TreeNode selectedModuloNode) {
        this.selectedModuloNode = selectedModuloNode;
    }

    public boolean isBMuestraObs() {
        return BMuestraObs;
    }

    public void setBMuestraObs(boolean BMuestraObs) {
        this.BMuestraObs = BMuestraObs;
    }

    public boolean isBActivo() {
        return BActivo;
    }

    public void setBActivo(boolean BActivo) {
        this.BActivo = BActivo;
    }

    public List<Modulo> getLstModuloPadre() {
        return lstModuloPadre;
    }

    public void setLstModuloPadre(List<Modulo> lstModuloPadre) {
        this.lstModuloPadre = lstModuloPadre;
    }

    public Modulo getSelectedModuloPadre() {
        return selectedModuloPadre;
    }

    public void setSelectedModuloPadre(Modulo selectedModuloPadre) {
        this.selectedModuloPadre = selectedModuloPadre;
    }

    public List<General> getLstTipoModulo() {
        return lstTipoModulo;
    }

    public void setLstTipoModulo(List<General> lstTipoModulo) {
        this.lstTipoModulo = lstTipoModulo;
    }

    public Map<String, String> getMapaTipoModulo() {
        return mapaTipoModulo;
    }

    public void setMapaTipoModulo(Map<String, String> mapaTipoModulo) {
        this.mapaTipoModulo = mapaTipoModulo;
    }

    public ConfiguracionModulo getSelectedConfiguracion() {
        return selectedConfiguracion;
    }

    public void setSelectedConfiguracion(ConfiguracionModulo selectedConfiguracion) {
        this.selectedConfiguracion = selectedConfiguracion;
    }

    public int getNumTiempoBloqueoSinuso() {
        return numTiempoBloqueoSinuso;
    }

    public void setNumTiempoBloqueoSinuso(int numTiempoBloqueoSinuso) {
        this.numTiempoBloqueoSinuso = numTiempoBloqueoSinuso;
    }

    public int getNumTiempoSesion() {
        return numTiempoSesion;
    }

    public void setNumTiempoSesion(int numTiempoSesion) {
        this.numTiempoSesion = numTiempoSesion;
    }
    
}
